﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq.Expressions;
using Redbrick.Silverlight.Common;

namespace Redbrick.Silverlight.Common
{
    public class ValueChangedEventArgs<_type> : EventArgs
    {
        public ValueChangedEventArgs(_type oldValue, _type newValue)
        {
            this.OldValue = OldValue;
            this.NewValue = NewValue;
        }

        public _type OldValue { get; private set; }
        public _type NewValue { get; private set; }
    }


    public class Watchable<_type> : Observable
    {

        #region Declarations

        private _type _value;
        private _type _previous;

        #endregion Declarations

        #region Constructor

        public Watchable() { }
        public Watchable(_type value)
        {
            this.Value = value;
        }

        #endregion Constructor

        #region Methods

        private bool CheckEquals(_type newValue)
        {
            if (newValue == null && this.Value != null) return false;
            if (newValue != null && this.Value == null) return false;
            return newValue.Equals(this.Value);

        }
        public event EventHandler<ValueChangedEventArgs<_type>> Updated;
        protected override bool OnPropertyChanged(PropertyChangedEventArgs args)
        {
            bool ret = base.OnPropertyChanged(args);
            var handler = this.Updated;
            if (handler != null)
            {
                handler(this, new ValueChangedEventArgs<_type>(this._previous, this._value));
            }
            return ret;
        }
        public static implicit operator _type(Watchable<_type> w) { return w.Value; }
        public static implicit operator Watchable<_type>(_type v) { return new Watchable<_type>(v); }

        public _type Value
        {
            get { return this._value; }
            set
            {
                if (!this.CheckEquals(value))
                {
                    this._previous = _value;
                    this._value = value;
                    RaisePropertyChanged(() => this.Value);
                }

            }
        }

        #endregion Methods

    }
}
